Day 21 - Exploratory Data Analysis af adgangsgrundlag for vidergående uddannelser

Published

August 6, 2025

Exploratory Data Analysis af adgangsgrundlag for videregående uddannelser

Data hentet fra UFM - Link

import pandas as pd
import numpy as np
df = pd.read_excel("data/day21/Ansøgere_adgangsgrundlag.xlsx")
/Users/jonskogland/Documents/hjemmeside - Jon Skogland/lokopu.github.io/venv/lib/python3.13/site-packages/openpyxl/styles/stylesheet.py:237: UserWarning: Workbook contains no default style, apply openpyxl's default
  warn("Workbook contains no default style, apply openpyxl's default")
df
Den Koordinerede Tilmelding Unnamed: 1 Unnamed: 2 1. prioritets-ansøgere fordelt på adgangsgrundlag Unnamed: 4 Unnamed: 5 Unnamed: 6 Unnamed: 7 Unnamed: 8 Unnamed: 9 ... Unnamed: 11 Unnamed: 12 Unnamed: 13 Unnamed: 14 Unnamed: 15 Unnamed: 16 Unnamed: 17 Unnamed: 18 Unnamed: 19 Unnamed: 20
0 NaN NaN NaN 22-juli-2024 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 NaN NaN NaN 1=stx NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN NaN 2=hf NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 NaN NaN NaN 3=hhx NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
944 8800 Erhvervsakademi Dania 84410 Produktionsteknolog, Randers SØ, Studiestart: ... 6 NaN 1.0 1.0 NaN 1.0 ... NaN NaN 1.0 NaN NaN NaN 1.0 NaN NaN NaN
945 8800 Erhvervsakademi Dania 86160 Service- og oplevelsesøkonom, Randers SØ, Stud... 15 1 7.0 1.0 3.0 NaN ... NaN NaN 1.0 1.0 NaN NaN NaN 1.0 NaN NaN
946 8800 Erhvervsakademi Dania 86164 Service- og oplevelsesøkonom, Randers SØ, E-læ... 45 NaN 12.0 10.0 3.0 4.0 ... NaN NaN 5.0 7.0 NaN 1.0 NaN 1.0 1.0 1.0
947 8800 Erhvervsakademi Dania 86166 Service- og oplevelsesøkonom, Randers SØ, E-læ... 9 NaN 1.0 3.0 4.0 NaN ... NaN NaN 1.0 NaN NaN NaN NaN NaN NaN NaN
948 8800 Erhvervsakademi Dania 87110 Logistikøkonom , Hobro, Studiestart: sommerstart 15 NaN 4.0 5.0 4.0 1.0 ... NaN NaN NaN NaN NaN 1.0 NaN NaN NaN NaN

949 rows × 21 columns

Her ses det at dataframe’en har nogle header rækker øverst som skal filtreres fra, samtidigt er der data som skal bruges til at indsætte navne på adgangsgrundlagene for kolonnerne fra 4 og frem. da der ellers kun står et tal som er svært at læse.

adgange = df.head(17)
adgange = adgange.iloc[2:,3]
adgange = adgange.str.split("=", expand=True)
adgange = adgange.rename(columns={0: "id", 1: "adgangsgrundlag"})
adgange
id adgangsgrundlag
2 1 stx
3 2 hf
4 3 hhx
5 4 htx
6 5 International Baccalaureate (IB)
7 6 GIF
8 7 Adgangseksamen for ingeniøruddannelser
9 8 Erhvervsuddannelse (EUD)
10 9 Andet adgangsgrundlag
11 10 International Baccalaureate (IB) fra udlandet
12 11 Anden adgangsgivende eksamen fra ud-landet
13 12 eux
14 13 eux 1. del
15 14 Færøsk gymnasial eksamen
16 15 Grønlandsk gymnasial eksamen
df = df.iloc[18:]
new_header = df.iloc[0]
df = df[1:]
df.columns = new_header 

Så er hoveddataene fra excelarket korrekt afgrænset og det har fået de korrekte kolonner

df
18 InstNr InstNavn OptNr OptNavn I alt Uoplyst 1.0 2.0 3.0 4.0 ... 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0
19 1000 Københavns Universitet 10110 Medicin, København Ø, Studiestart: sommer- og ... 1687 4 1107.0 111.0 14.0 116.0 ... 11.0 NaN 1.0 10.0 11.0 240.0 1.0 2.0 13.0 1.0
20 1000 Københavns Universitet 10112 Medicin, Køge, Studiestart: sommer- og vinters... 234 NaN 147.0 25.0 1.0 38.0 ... NaN NaN 2.0 3.0 1.0 10.0 NaN NaN NaN NaN
21 1000 Københavns Universitet 10115 Folkesundhedsvidenskab, København K, Studiesta... 88 NaN 81.0 3.0 NaN 1.0 ... NaN NaN NaN NaN NaN 2.0 NaN NaN NaN 1.0
22 1000 Københavns Universitet 10117 Farmaci, København Ø, Studiestart: sommerstart 291 NaN 194.0 32.0 2.0 44.0 ... 7.0 NaN NaN 3.0 NaN 4.0 NaN NaN 3.0 NaN
23 1000 Københavns Universitet 10120 Odontologi, København Ø, Studiestart: sommerstart 471 1 310.0 46.0 8.0 54.0 ... 8.0 NaN 1.0 5.0 NaN 27.0 NaN NaN 7.0 NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
944 8800 Erhvervsakademi Dania 84410 Produktionsteknolog, Randers SØ, Studiestart: ... 6 NaN 1.0 1.0 NaN 1.0 ... NaN NaN 1.0 NaN NaN NaN 1.0 NaN NaN NaN
945 8800 Erhvervsakademi Dania 86160 Service- og oplevelsesøkonom, Randers SØ, Stud... 15 1 7.0 1.0 3.0 NaN ... NaN NaN 1.0 1.0 NaN NaN NaN 1.0 NaN NaN
946 8800 Erhvervsakademi Dania 86164 Service- og oplevelsesøkonom, Randers SØ, E-læ... 45 NaN 12.0 10.0 3.0 4.0 ... NaN NaN 5.0 7.0 NaN 1.0 NaN 1.0 1.0 1.0
947 8800 Erhvervsakademi Dania 86166 Service- og oplevelsesøkonom, Randers SØ, E-læ... 9 NaN 1.0 3.0 4.0 NaN ... NaN NaN 1.0 NaN NaN NaN NaN NaN NaN NaN
948 8800 Erhvervsakademi Dania 87110 Logistikøkonom , Hobro, Studiestart: sommerstart 15 NaN 4.0 5.0 4.0 1.0 ... NaN NaN NaN NaN NaN 1.0 NaN NaN NaN NaN

930 rows × 21 columns

Ovenstående dataframe er dog i wide format og det vil derfor være besværligt at lave analyse på. Derfor skal kolonnerne 1-15 pivoteres sådan at vi får to kolonner i stedet: “adgangsrundlag”, hvor værdierne vil være teksten på den uddannelse de studerende kommer fra, og “ansøgere” som vil være det antal som har søgt uddannelsen fra det givne adgangsgrundlag - denne vil erstatte “i alt” kolonnen da denne kan summeres efterfølgende.

res = df.columns.tolist()
res
['InstNr',
 'InstNavn',
 'OptNr',
 'OptNavn',
 'I alt',
 'Uoplyst',
 np.float64(1.0),
 np.float64(2.0),
 np.float64(3.0),
 np.float64(4.0),
 np.float64(5.0),
 np.float64(6.0),
 np.float64(7.0),
 np.float64(8.0),
 np.float64(9.0),
 np.float64(10.0),
 np.float64(11.0),
 np.float64(12.0),
 np.float64(13.0),
 np.float64(14.0),
 np.float64(15.0)]
res = res[0:5]
melted = pd.melt(df, id_vars=res)
melted
InstNr InstNavn OptNr OptNavn I alt 18 value
0 1000 Københavns Universitet 10110 Medicin, København Ø, Studiestart: sommer- og ... 1687 Uoplyst 4
1 1000 Københavns Universitet 10112 Medicin, Køge, Studiestart: sommer- og vinters... 234 Uoplyst NaN
2 1000 Københavns Universitet 10115 Folkesundhedsvidenskab, København K, Studiesta... 88 Uoplyst NaN
3 1000 Københavns Universitet 10117 Farmaci, København Ø, Studiestart: sommerstart 291 Uoplyst NaN
4 1000 Københavns Universitet 10120 Odontologi, København Ø, Studiestart: sommerstart 471 Uoplyst 1
... ... ... ... ... ... ... ...
14875 8800 Erhvervsakademi Dania 84410 Produktionsteknolog, Randers SØ, Studiestart: ... 6 15.0 NaN
14876 8800 Erhvervsakademi Dania 86160 Service- og oplevelsesøkonom, Randers SØ, Stud... 15 15.0 NaN
14877 8800 Erhvervsakademi Dania 86164 Service- og oplevelsesøkonom, Randers SØ, E-læ... 45 15.0 1.0
14878 8800 Erhvervsakademi Dania 86166 Service- og oplevelsesøkonom, Randers SØ, E-læ... 9 15.0 NaN
14879 8800 Erhvervsakademi Dania 87110 Logistikøkonom , Hobro, Studiestart: sommerstart 15 15.0 NaN

14880 rows × 7 columns

Ny mangler vi dog at “mappe” de forskelle adgangsgrundlag id’er sådan at der står det faktiske adgangsgrundlag og ikke tallet.

d = {}
for index, row in adgange.iterrows():
    d[float(row["id"])] = row["adgangsgrundlag"]

d
{1.0: 'stx',
 2.0: 'hf',
 3.0: 'hhx',
 4.0: 'htx',
 5.0: 'International Baccalaureate (IB)',
 6.0: 'GIF',
 7.0: 'Adgangseksamen for ingeniøruddannelser',
 8.0: 'Erhvervsuddannelse (EUD)',
 9.0: 'Andet adgangsgrundlag',
 10.0: 'International Baccalaureate (IB) fra udlandet',
 11.0: 'Anden adgangsgivende eksamen fra ud-landet',
 12.0: 'eux',
 13.0: 'eux 1. del',
 14.0: 'Færøsk gymnasial eksamen',
 15.0: 'Grønlandsk gymnasial eksamen'}
pd.set_option('future.no_silent_downcasting', False)
#melted[18] = melted[18].replace("Uoplyst", np.nan).infer_objects(copy=False)
melted["adgangsgrundlag"] = melted[18].map(d)
melted = melted.drop(columns=18)
melted = melted.rename(columns={"value": "antal"})
melted["adgangsgrundlag"] = melted["adgangsgrundlag"].replace(np.nan, "Uoplyst").infer_objects(copy=False)
melted
InstNr InstNavn OptNr OptNavn I alt antal adgangsgrundlag
0 1000 Københavns Universitet 10110 Medicin, København Ø, Studiestart: sommer- og ... 1687 4 Uoplyst
1 1000 Københavns Universitet 10112 Medicin, Køge, Studiestart: sommer- og vinters... 234 NaN Uoplyst
2 1000 Københavns Universitet 10115 Folkesundhedsvidenskab, København K, Studiesta... 88 NaN Uoplyst
3 1000 Københavns Universitet 10117 Farmaci, København Ø, Studiestart: sommerstart 291 NaN Uoplyst
4 1000 Københavns Universitet 10120 Odontologi, København Ø, Studiestart: sommerstart 471 1 Uoplyst
... ... ... ... ... ... ... ...
14875 8800 Erhvervsakademi Dania 84410 Produktionsteknolog, Randers SØ, Studiestart: ... 6 NaN Grønlandsk gymnasial eksamen
14876 8800 Erhvervsakademi Dania 86160 Service- og oplevelsesøkonom, Randers SØ, Stud... 15 NaN Grønlandsk gymnasial eksamen
14877 8800 Erhvervsakademi Dania 86164 Service- og oplevelsesøkonom, Randers SØ, E-læ... 45 1.0 Grønlandsk gymnasial eksamen
14878 8800 Erhvervsakademi Dania 86166 Service- og oplevelsesøkonom, Randers SØ, E-læ... 9 NaN Grønlandsk gymnasial eksamen
14879 8800 Erhvervsakademi Dania 87110 Logistikøkonom , Hobro, Studiestart: sommerstart 15 NaN Grønlandsk gymnasial eksamen

14880 rows × 7 columns

# Finde InstNavn for CBS
melted["InstNavn"].unique()
array(['Københavns Universitet',
       'Copenhagen Business School - Handelshøjskolen',
       'IT-Universitetet i København', 'Danmarks Tekniske Universitet',
       'Roskilde Universitet', 'Syddansk Universitet',
       'Aarhus Universitet', 'Aalborg Universitet',
       'Det Kongelige Akademi - Arkitektur, Design, Konservering',
       'Arkitektskolen Aarhus', 'Designskolen Kolding',
       'Københavns Professionshøjskole', 'Professionshøjskolen Absalon',
       'Professionshøjskolen UC Syddanmark',
       'UCL Erhvervsakademi og Professionshøjskole',
       'Professionshøjskolen VIA University College',
       'Professionshøjskolen University College Nordjylland',
       'Danmarks Medie- og Journalisthøjskole', 'Den Frie Lærerskole',
       'Maskinmesterskolen København',
       'Svendborg International Maritime Academy, SIMAC',
       'Fredericia Maskinmesterskole', 'Aarhus Maskinmesterskole',
       'MARTEC - Maritime and Polytechnic University College',
       'Erhvervsakademiet Copenhagen Business Academy',
       'Københavns Erhvervsakademi (KEA)',
       'Zealand Sjællands Erhvervsakademi', 'IBA Erhvervsakademi Kolding',
       'Erhvervsakademi SydVest', 'Erhvervsakademi MidtVest',
       'Erhvervsakademi Aarhus', 'Erhvervsakademi Dania'], dtype=object)
# Filtrere CBS
CBS = melted[melted["InstNavn"] == "Copenhagen Business School - Handelshøjskolen"]
CBS
InstNr InstNavn OptNr OptNavn I alt antal adgangsgrundlag
75 1300 Copenhagen Business School - Handelshøjskolen 13010 Erhvervsøkonomi, HA, Frederiksberg, Studiestar... 925 NaN Uoplyst
76 1300 Copenhagen Business School - Handelshøjskolen 13015 Erhvervsøkonomi-informationsteknologi, HA (it.... 223 NaN Uoplyst
77 1300 Copenhagen Business School - Handelshøjskolen 13020 Erhvervsøkonomi-erhvervsret, HA (jur.), Freder... 305 NaN Uoplyst
78 1300 Copenhagen Business School - Handelshøjskolen 13023 Erhvervsøkonomi og markeds- og kulturanalyse, ... 251 NaN Uoplyst
79 1300 Copenhagen Business School - Handelshøjskolen 13025 Erhvervsøkonomi-matematik, HA (mat.), Frederik... 89 NaN Uoplyst
... ... ... ... ... ... ... ...
14039 1300 Copenhagen Business School - Handelshøjskolen 13085 Business, Asian Language and Culture - Interna... 71 NaN Grønlandsk gymnasial eksamen
14040 1300 Copenhagen Business School - Handelshøjskolen 13090 Business, Asian Language and Culture - Interna... 72 NaN Grønlandsk gymnasial eksamen
14041 1300 Copenhagen Business School - Handelshøjskolen 13100 Business Administration and Digital Management... 601 NaN Grønlandsk gymnasial eksamen
14042 1300 Copenhagen Business School - Handelshøjskolen 13280 International Shipping and Trade, Frederiksber... 272 NaN Grønlandsk gymnasial eksamen
14043 1300 Copenhagen Business School - Handelshøjskolen 13290 Europæisk business, HA i europæisk business, F... 273 NaN Grønlandsk gymnasial eksamen

304 rows × 7 columns

Tilføjelse af procent kolonne

import altair as alt
# lave ny kolonnen med procent af total med givne adgangsgrundlag
melted["procent"] = (melted["antal"] / melted["I alt"])
melted.dtypes
InstNr             object
InstNavn           object
OptNr              object
OptNavn            object
I alt              object
antal              object
adgangsgrundlag    object
procent            object
dtype: object
melted['procent'].astype('float')
0        0.002371
1             NaN
2             NaN
3             NaN
4        0.002123
           ...   
14875         NaN
14876         NaN
14877    0.022222
14878         NaN
14879         NaN
Name: procent, Length: 14880, dtype: float64
cbs_stx = melted[(melted['InstNr']== 1300) & (melted['adgangsgrundlag'] == 'stx')]
alt.Chart(cbs_stx).mark_point().encode(
    y=alt.Y('OptNavn', axis=alt.Axis(labelAngle=0, labelLimit=0, titlePadding=400)),
    x="procent"
)

Her kan man altså se procentandelen af studerende for hver CBS Bachelor uddannelse, hvor den studerende har STX som adgangsgrundlag. Her giver det mening at de uddannelse med en STX procent på under 0.3 er på engelsk, hvor er vil være mange udenlandske studerende som derfor ikke har gået på STX. De engelske uddannelse ville give mening at analysere ved at se procentandelen af STX hvor udenlandske studerende er talt fra for at få en ide om hvilke grundlag de danske studerende har.

cbs = melted[melted['InstNr'] == 1300]
pd.set_option('future.no_silent_downcasting', True)
cbs.loc[:, 'antal'] = cbs['antal'].fillna(0)
cbs.loc[:, 'procent'] = cbs['procent'].fillna(0)
cbs
InstNr InstNavn OptNr OptNavn I alt antal adgangsgrundlag procent
75 1300 Copenhagen Business School - Handelshøjskolen 13010 Erhvervsøkonomi, HA, Frederiksberg, Studiestar... 925 0 Uoplyst 0
76 1300 Copenhagen Business School - Handelshøjskolen 13015 Erhvervsøkonomi-informationsteknologi, HA (it.... 223 0 Uoplyst 0
77 1300 Copenhagen Business School - Handelshøjskolen 13020 Erhvervsøkonomi-erhvervsret, HA (jur.), Freder... 305 0 Uoplyst 0
78 1300 Copenhagen Business School - Handelshøjskolen 13023 Erhvervsøkonomi og markeds- og kulturanalyse, ... 251 0 Uoplyst 0
79 1300 Copenhagen Business School - Handelshøjskolen 13025 Erhvervsøkonomi-matematik, HA (mat.), Frederik... 89 0 Uoplyst 0
... ... ... ... ... ... ... ... ...
14039 1300 Copenhagen Business School - Handelshøjskolen 13085 Business, Asian Language and Culture - Interna... 71 0 Grønlandsk gymnasial eksamen 0
14040 1300 Copenhagen Business School - Handelshøjskolen 13090 Business, Asian Language and Culture - Interna... 72 0 Grønlandsk gymnasial eksamen 0
14041 1300 Copenhagen Business School - Handelshøjskolen 13100 Business Administration and Digital Management... 601 0 Grønlandsk gymnasial eksamen 0
14042 1300 Copenhagen Business School - Handelshøjskolen 13280 International Shipping and Trade, Frederiksber... 272 0 Grønlandsk gymnasial eksamen 0
14043 1300 Copenhagen Business School - Handelshøjskolen 13290 Europæisk business, HA i europæisk business, F... 273 0 Grønlandsk gymnasial eksamen 0

304 rows × 8 columns

alt.Chart(cbs).mark_bar().encode(
    y=alt.Y('OptNavn', axis=alt.Axis(labelAngle=0, labelLimit=0, titlePadding=400)),
    x="procent",
    color='adgangsgrundlag'
)

Her kan vi se fordelingen af adgangsgrundlag mere tydeligt. Hvor STX og HHX dominerer på de danske uddannelser hos CBS.

Til en videre analyse, ville det være interessant at sammenligne fordelingen med procentandelen af adgangsgrundlagene for STX, HHX osv. for at tyde om HHX’ere i højere grad søger CBS end STX relativt til antal studerende. Desuden at sammenligne med andre erhvervsøkonomiske uddannelser og se hvorledes deres fordelinger er.